From a606f89f0e99a4eefced04faa58118240bbf5b45 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 11 Aug 2005 16:48:36 +0000 Subject: [PATCH] Clean up event-channel notification code in Xen. Signed-off-by: Keir Fraser --- xen/arch/ia64/vcpu.c | 8 ++++++++ xen/arch/x86/mm.c | 1 + xen/include/asm-x86/event.h | 13 +++++++++++++ xen/include/xen/event.h | 29 +++++++---------------------- xen/include/xen/sched.h | 7 +++---- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/xen/arch/ia64/vcpu.c b/xen/arch/ia64/vcpu.c index ed22389ab5..d6f224a425 100644 --- a/xen/arch/ia64/vcpu.c +++ b/xen/arch/ia64/vcpu.c @@ -587,6 +587,14 @@ void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector) set_bit(vector,PSCBX(vcpu,irr)); PSCB(vcpu,pending_interruption) = 1; } + + /* Keir: I think you should unblock when an interrupt is pending. */ + { + int running = test_bit(_VCPUF_running, &vcpu->vcpu_flags); + vcpu_unblock(vcpu); + if ( running ) + smp_send_event_check_cpu(vcpu->processor); + } } void early_tick(VCPU *vcpu) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 827aa23463..ff4de80b6b 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -95,6 +95,7 @@ #include #include #include +#include #include #include #include diff --git a/xen/include/asm-x86/event.h b/xen/include/asm-x86/event.h index e7b5cda8b1..d491d24313 100644 --- a/xen/include/asm-x86/event.h +++ b/xen/include/asm-x86/event.h @@ -11,6 +11,19 @@ static inline void evtchn_notify(struct vcpu *v) { + /* + * NB1. 'vcpu_flags' and 'processor' must be checked /after/ update of + * pending flag. These values may fluctuate (after all, we hold no + * locks) but the key insight is that each change will cause + * evtchn_upcall_pending to be polled. + * + * NB2. We save VCPUF_running across the unblock to avoid a needless + * IPI for domains that we IPI'd to unblock. + */ + int running = test_bit(_VCPUF_running, &v->vcpu_flags); + vcpu_unblock(v); + if ( running ) + smp_send_event_check_cpu(v->processor); } #endif diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index 05683344ca..8f527b0c83 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -26,30 +26,14 @@ static inline void evtchn_set_pending(struct vcpu *v, int port) { struct domain *d = v->domain; shared_info_t *s = d->shared_info; - int running; - /* These three operations must happen in strict order. */ + /* These four operations must happen in strict order. */ if ( !test_and_set_bit(port, &s->evtchn_pending[0]) && !test_bit (port, &s->evtchn_mask[0]) && - !test_and_set_bit(port>>5, &v->vcpu_info->evtchn_pending_sel) ) + !test_and_set_bit(port>>5, &v->vcpu_info->evtchn_pending_sel) && + !test_and_set_bit(0, &v->vcpu_info->evtchn_upcall_pending) ) { - /* The VCPU pending flag must be set /after/ update to evtchn-pend. */ - set_bit(0, &v->vcpu_info->evtchn_upcall_pending); evtchn_notify(v); - - /* - * NB1. 'vcpu_flags' and 'processor' must be checked /after/ update of - * pending flag. These values may fluctuate (after all, we hold no - * locks) but the key insight is that each change will cause - * evtchn_upcall_pending to be polled. - * - * NB2. We save VCPUF_running across the unblock to avoid a needless - * IPI for domains that we IPI'd to unblock. - */ - running = test_bit(_VCPUF_running, &v->vcpu_flags); - vcpu_unblock(v); - if ( running ) - smp_send_event_check_cpu(v->processor); } } @@ -73,8 +57,9 @@ static inline void send_guest_virq(struct vcpu *v, int virq) */ extern void send_guest_pirq(struct domain *d, int pirq); -#define event_pending(_d) \ - ((_d)->vcpu_info->evtchn_upcall_pending && \ - !(_d)->vcpu_info->evtchn_upcall_mask) +/* Note: Bitwise operations result in fast code with no branches. */ +#define event_pending(v) \ + ((v)->vcpu_info->evtchn_upcall_pending & \ + ~(v)->vcpu_info->evtchn_upcall_mask) #endif /* __XEN_EVENT_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index cc151badda..45e04fc93d 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -297,10 +297,9 @@ unsigned long __hypercall_create_continuation( (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \ (unsigned long)(_a4), (unsigned long)(_a5), (unsigned long)(_a6)) -#define hypercall_preempt_check() (unlikely( \ - softirq_pending(smp_processor_id()) | \ - (!!current->vcpu_info->evtchn_upcall_pending & \ - !current->vcpu_info->evtchn_upcall_mask) \ +#define hypercall_preempt_check() (unlikely( \ + softirq_pending(smp_processor_id()) | \ + event_pending(current) \ )) /* This domain_hash and domain_list are protected by the domlist_lock. */ -- 2.30.2